//: C05:NestFriend.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 1999
// Copyright notice in Copyright.txt
// Nested friends
#include <iostream>
#include <cstring> // memset()
using namespace std;
const int sz = 20;

struct Holder {
private:
    int a[sz];
public:
    void initialize();
    struct Pointer {
private:
        Holder* h;
        int* p;
public:
        void initialize(Holder* h);
        // Move around in the array:
        void next();
        void previous();
        void top();
        void end();
        // Access values:
        int read();
        void set(int i);
    };
    friend Holder::Pointer;
};

void Holder::initialize()
{
    memset(a, 0, sz * sizeof(int));
}

void Holder::Pointer::initialize(Holder* h)
{
    h = h;
    p = h->a;
}

void Holder::Pointer::next()
{
    if (p < &(h->a[sz - 1])) p++;
}

void Holder::Pointer::previous()
{
    if (p > &(h->a[0])) p--;
}

void Holder::Pointer::top()
{
    p = &(h->a[0]);
}

void Holder::Pointer::end()
{
    p = &(h->a[sz - 1]);
}

int Holder::Pointer::read()
{
    return *p;
}

void Holder::Pointer::set(int i)
{
    *p = i;
}

int main()
{
    Holder h;
    Holder::Pointer hp, hp2;
    int i;

    h.initialize();
    hp.initialize(&h);
    hp2.initialize(&h);
    for (i = 0; i < sz; i++) {
        hp.set(i);
        hp.next();
    }
    hp.top();
    hp2.end();
    for (i = 0; i < sz; i++) {
        cout << "hp = " << hp.read()
             << ", hp2 = " << hp2.read() << endl;
        hp.next();
        hp2.previous();
    }
} ///:~
